package com.jiyongjun.bms.base.configurer;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import com.jiyongjun.bms.tool.DateUtils;
import com.jiyongjun.bms.tool.dto.Result;
import com.jiyongjun.bms.tool.exception.BizException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.NoHandlerFoundException;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.Collections;
import java.util.List;

/**
 * <h2></h2>
 * description:
 *
 * @author yongjun.ji
 * @since 1.0 2019/5/29
 */
@Configuration
@Slf4j
public class CustomWebMvcConfigurer implements WebMvcConfigurer {

    @Override
    public void extendHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {
        resolvers.add(((request, response, handler, ex) -> {
            Result result;
            if (ex instanceof BizException) {
                // 业务失败的异常，如“账号或密码错误”
                result = Result.bizFailed((BizException) ex);
            } else if (ex instanceof NoHandlerFoundException) {
                result = Result.bizFailed("接口 [" + request.getRequestURI() + "] 不存在");
            } else if (ex instanceof ServletException) {
                result = Result.serviceFailed(ex);
            } else {
                result = Result.serviceFailed(ex);
                String message;
                if (handler instanceof HandlerMethod) {
                    HandlerMethod handlerMethod = (HandlerMethod) handler;
                    message = String.format("接口 [%s] 出现异常，方法：%s.%s，异常摘要：%s",
                            request.getRequestURI(),
                            handlerMethod.getBean().getClass().getName(),
                            handlerMethod.getMethod().getName(),
                            ex.getMessage());
                } else {
                    message = ex.getMessage();
                }
                log.error(message, ex);
            }
            responseResult(response, result);
            return new ModelAndView();
        }));
    }

    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();

        FastJsonConfig config = new FastJsonConfig();
        config.setDateFormat(DateUtils.MIDDLE_PATTERN);
        config.setSerializerFeatures(SerializerFeature.WriteMapNullValue);

        converter.setFastJsonConfig(config);
        converter.setDefaultCharset(Charset.forName("UTF-8"));
        converter.setSupportedMediaTypes(Collections.singletonList(MediaType.APPLICATION_JSON_UTF8));

        converters.add(converter);
    }

    private void responseResult(HttpServletResponse response, Result result) {
        response.setCharacterEncoding("UTF-8");
        response.setHeader("Content-type", "application/json;charset=UTF-8");
        response.setStatus(200);
        try {
            response.getWriter().write(JSON.toJSONString(result));
        } catch (IOException ex) {
            log.error(ex.getMessage());
        }
    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        // registry.addResourceHandler("/**").addResourceLocations("classpath:/META-INF/resources/").setCachePeriod(0);
        // registry.addResourceHandler("/plugin/**", "/static/**")
        //         .addResourceLocations("classpath:/plugin/", "classpath:/static/");
        // registry.addResourceHandler("/ftl/**").addResourceLocations("classpath:/ftl/");
        // registry.addResourceHandler("/images/**").addResourceLocations("file:" + imagePath);
        // registry.addResourceHandler("/img/**").addResourceLocations("file:" + imagePath);
        // registry.addResourceHandler("/file/**").addResourceLocations("file:" + imagePath);
        // registry.addResourceHandler("/favicon.ico").addResourceLocations("classpath:/static/");
    }
}
